package service

import (
	sqlc "bgs/db/sqlc"
	"bgs/util"
	"context"
	"database/sql"
	"fmt"
)

// EnsureActivityExposureStat 确保ActivityExposureStat对于一个活动始终有一条记录
func (s *ActivityServiceImp) EnsureActivityExposureStat(ctx context.Context, q *sqlc.Queries, withLock bool, activityID int64) (activityExposureStat sqlc.ActivityExposureStat, err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	var sqlErr error
	if withLock {
		activityExposureStat, sqlErr = q.GetActivityExposureStatByActivityIDToLock(ctx, activityID)
	} else {
		activityExposureStat, sqlErr = q.GetActivityExposureStatByActivityID(ctx, activityID)
	}

	if sqlErr != nil {
		if sql.ErrNoRows != sqlErr {
			err = sqlErr
			return
		}
		slog.Infof("找不到活动订单统计记录")
		cActivity := s.cacher.FetchActivity(activityID)
		if cActivity == nil {
			err = fmt.Errorf("not found activity:%d", activityID)
			return
		}
		activityExposureStat, err = q.UpsertActivityExposureStat(ctx, sqlc.UpsertActivityExposureStatParams{
			BrandID:          cActivity.BrandID,
			ActivityID:       activityID,
			RootActivityID:   sqlc.NInt64FromInt64(cActivity.RootID),
			ParentActivityID: sqlc.NInt64FromInt64(cActivity.ParentID),
		})
		if err != nil {
			return
		}
	}
	slog.Infof("确保活动曝光记录并返回 ok")
	return
}

// UpdateActivityExposureStatSinceAccessedByC C端用户访问活动更新活动曝光
func (s *ActivityServiceImp) UpdateActivityExposureStatSinceAccessedByC(ctx context.Context, q *sqlc.Queries, activityPtr *sqlc.Activity) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	activityID := activityPtr.ID
	activityExposureStatLocked, err := s.EnsureActivityExposureStat(ctx, q, true, activityID)
	if err != nil {
		return
	}
	slog.Infof("1、Exposure-确保获取锁定的活动订单统计记录(%d) ok", activityID)
	slog.Infof("2、Exposure 更新前latest_accessed(%d),pv(%d),uv(%d) ok",
		util.GoTimeToString(activityExposureStatLocked.LatestAccessed),
		activityExposureStatLocked.Pv,
		activityExposureStatLocked.Uv,
	)
	aggRet, err := q.AggsToActivityLatestTimePvUvByActivityID(ctx, activityID) // 包含当前这个订单,订单用户在活动下的统计数==1表示是新用户
	if err != nil {
		return
	}
	slog.Infof("2、统计当前用户访问活动后的的latest_accessed,pv,uv ok")

	err = q.UpdateActivityExposureStatSinceActivityExposure(ctx, sqlc.UpdateActivityExposureStatSinceActivityExposureParams{
		ActivityID:     activityID,
		LatestAccessed: aggRet.LatestAccessed,
		Pv:             aggRet.Pv,
		Uv:             aggRet.Uv,
	})
	if err != nil {
		return
	}
	slog.Infof("2、更新后latest_accessed(%d),pv(%d),uv(%d) ok",
		util.GoTimeToString(aggRet.LatestAccessed),
		aggRet.Pv,
		aggRet.Uv,
	)

	slog.Infof("C端用户访问活动更新活动曝光 ok")
	return
}

// UpdateActivityExposureStatSinceInteractedByC C端用户与活动互动更新活动曝光
func (s *ActivityServiceImp) UpdateActivityExposureStatSinceInteractedByC(ctx context.Context, q *sqlc.Queries, activityID int64) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	activityExposureStatLocked, err := s.EnsureActivityExposureStat(ctx, q, true, activityID)
	if err != nil {
		return
	}
	slog.Infof("1、InteractedByC-确保获取锁定的活动订单统计记录(%d) ok", activityID)
	slog.Infof("2、更新前iv(%d) ok",
		activityExposureStatLocked.Iv,
	)
	aggRet, err := q.AggsToActivityInteraviveCountOfUserProcedureByActivityID(ctx, activityID) // 包含当前这个订单,订单用户在活动下的统计数==1表示是新用户
	if err != nil {
		return
	}
	slog.Infof("2、统计当前用户与活动交互后的iv ok")

	iv := int32(aggRet)

	err = q.UpdateActivityExposureStatSinceActivityUserInteracted(ctx, sqlc.UpdateActivityExposureStatSinceActivityUserInteractedParams{
		ActivityID: activityID,
		Iv:         iv,
	})
	if err != nil {
		return
	}
	slog.Infof("3、更新后iv(%d) ok", iv)

	slog.Infof("C端用户与活动互动更新活动曝光 ok")
	return
}

// UpdateActivityExposureStatSinceOrderCreated 交易类活动下单更新活动曝光
func (s *ActivityServiceImp) UpdateActivityExposureStatSinceOrderCreated(ctx context.Context, q *sqlc.Queries, activityID int64) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	activityExposureStatLocked, err := s.EnsureActivityExposureStat(ctx, q, true, activityID)
	if err != nil {
		return
	}
	slog.Infof("1、InteractedByC-确保获取锁定的活动订单统计记录(%d) ok", activityID)
	slog.Infof("2、更新前iv(%d) ok",
		activityExposureStatLocked.Iv,
	)
	countRet, err := q.CountUsersOrderedByActivityID(ctx, activityID)
	if err != nil {
		return
	}
	slog.Infof("2、统计当前订单创建后当前用户的订单数量 ok")

	iv := int32(countRet)

	err = q.UpdateActivityExposureStatSinceActivityUserInteracted(ctx, sqlc.UpdateActivityExposureStatSinceActivityUserInteractedParams{
		ActivityID: activityID,
		Iv:         iv,
	})
	if err != nil {
		return
	}
	slog.Infof("3、更新后iv(%d) ok", iv)

	slog.Infof("交易类活动下单更新活动曝光 ok")
	return
}

// EnsureActivityOrderStat 确保ActivityOrderStat对于一个活动始终有一条记录
func (s *ActivityServiceImp) EnsureActivityOrderStat(ctx context.Context, q *sqlc.Queries, withLock bool, activityID int64) (activityOrderStat sqlc.ActivityOrderStat, err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	var sqlErr error
	if withLock {
		activityOrderStat, sqlErr = q.GetActivityOrderStatByActivityIDToLock(ctx, activityID)
	} else {
		activityOrderStat, sqlErr = q.GetActivityOrderStatByActivityID(ctx, activityID)
	}

	if sqlErr != nil {
		if sql.ErrNoRows != sqlErr {
			err = sqlErr
			return
		}
		slog.Infof("找不到活动订单统计记录")
		cActivity := s.cacher.FetchActivity(activityID)
		if cActivity == nil {
			err = fmt.Errorf("not found activity:%d", activityID)
			return
		}
		activityOrderStat, err = q.UpsertActivityOrderStat(ctx, sqlc.UpsertActivityOrderStatParams{
			BrandID:          cActivity.BrandID,
			StoreID:          cActivity.StoreID,
			DistributorID:    cActivity.DistributeID,
			ActivityID:       activityID,
			RootActivityID:   sqlc.NInt64FromInt64(cActivity.RootID),
			ParentActivityID: sqlc.NInt64FromInt64(cActivity.ParentID),
		})
		if err != nil {
			return
		}
	}
	return
}

// EnsureActivityUserOrderStat 确保ActivityUserOrderStat对于一个活动始终有一条记录
func (s *ActivityServiceImp) EnsureActivityUserOrderStat(ctx context.Context, q *sqlc.Queries, withLock bool, activityID int64, userID int64) (activityUserOrderStat sqlc.ActivityUserOrderStat, err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	var sqlErr error
	if withLock {
		activityUserOrderStat, sqlErr = q.GetActivityUserOrderStatByActivityIDAndUserIDToLock(ctx, sqlc.GetActivityUserOrderStatByActivityIDAndUserIDToLockParams{
			ActivityID: activityID,
			UserID:     userID,
		})
	} else {
		activityUserOrderStat, sqlErr = q.GetActivityUserOrderStatByActivityIDAndUserID(ctx, sqlc.GetActivityUserOrderStatByActivityIDAndUserIDParams{
			ActivityID: activityID,
			UserID:     userID,
		})
	}

	if sqlErr != nil {
		if sql.ErrNoRows != sqlErr {
			err = sqlErr
			return
		}
		slog.Infof("找不到活动用户订单统计记录")
		cActivity := s.cacher.FetchActivity(activityID)
		if cActivity == nil {
			err = fmt.Errorf("not found activity:%d", activityID)
			return
		}
		activityUserOrderStat, err = q.UpsertActivityUserOrderStat(ctx, sqlc.UpsertActivityUserOrderStatParams{
			BrandID:          cActivity.BrandID,
			StoreID:          cActivity.StoreID,
			DistributorID:    cActivity.DistributeID,
			ActivityID:       activityID,
			RootActivityID:   sqlc.NInt64FromInt64(cActivity.RootID),
			ParentActivityID: sqlc.NInt64FromInt64(cActivity.ParentID),
			SpokesmanID:      sqlc.NInt64FromInt64(cActivity.SpokesmanID),
			SpokesmanUserID:  sqlc.NInt64FromInt64(cActivity.PubUserID),
			UserID:           userID,
		})
		if err != nil {
			return
		}
	}
	return
}

// UpdateActivityOrderStatSinceOrderPayed 新订单支付成功更新活动订单统计
func (s *ActivityServiceImp) UpdateActivityOrderStatSinceOrderPayed(ctx context.Context, q *sqlc.Queries, orderPtr *sqlc.Order) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	activityID := orderPtr.ActivityID
	activityOrderStatLocked, err := s.EnsureActivityOrderStat(ctx, q, true, activityID)
	if err != nil {
		return
	}
	slog.Infof("1、下单-确保获取锁定的活动订单统计记录(%d) ok", activityID)

	newBuyerCount, err := q.AggrBuyerCountOfOrderByActivityID(ctx, activityID) // 包含当前这个订单,订单用户在活动下的统计数==1表示是新用户
	if err != nil {
		return
	}
	slog.Infof("2、统计当前订单支付成功后订单活动的买家数量 ok")
	aggRetOfOrderForward, err := q.AggrOrderForwardByActivityID(ctx, activityID)
	if err != nil {
		return
	}
	slog.Infof("3、统计当前订单支付成功后订单活动的订单数量、订单金额、订单奖励金、微信手续费、平台手续费 ok")

	cActivity := s.GetCacheOwn(activityID)
	distributeAmount := activityOrderStatLocked.DistributeAmount
	if cActivity.StoreID.Valid {
		// cStore := s.cacher.FetchStore(cActivity.StoreID.Int64)
		// 统计活动分销佣金
		distributeAmount = 0
	}

	err = q.UpdateActivityOrderStatSinceOrderPayed(ctx, sqlc.UpdateActivityOrderStatSinceOrderPayedParams{
		ActivityID:         activityID,
		BuyerCount:         int32(newBuyerCount),
		OrderCount:         int32(aggRetOfOrderForward.OrderCount),
		OrderAmount:        aggRetOfOrderForward.OrderAmount,
		DistributeAmount:   distributeAmount,
		OrderBonus:         aggRetOfOrderForward.OrderBonus,
		Fee:                activityOrderStatLocked.Fee,
		WxpayCommission:    aggRetOfOrderForward.WxpayCommission,
		PlatformCommission: aggRetOfOrderForward.PlatformCommission,
	})
	if err != nil {
		return
	}

	slog.Infof("新订单支付成功更新活动订单统计的正向下单部分字段 ok")
	return
}

// UpdateActivityStatSinceOrderPayed 新订单支付成功更新活动用户订单统计
func (s *ActivityServiceImp) UpdateActivityUserOrderStatSinceOrderPayed(ctx context.Context, q *sqlc.Queries, orderPtr *sqlc.Order) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	activityID := orderPtr.ActivityID
	userID := orderPtr.UserID
	activityUserOrderStatLocked, err := s.EnsureActivityUserOrderStat(ctx, q, true, activityID, userID)
	if err != nil {
		return
	}
	slog.Infof("1、下单-确保获取锁定的活动用户订单统计记录(%d)(%d)(%d) ok", activityID, userID, activityUserOrderStatLocked.ID)

	aggRetOfOrderForward, err := q.AggrOrderForwardByActivityIDAndUserID(ctx, sqlc.AggrOrderForwardByActivityIDAndUserIDParams{
		ActivityID: activityID,
		UserID:     userID,
	})
	if err != nil {
		return
	}
	slog.Infof("2、统计当前订单支付成功后用该用户订单活动的订单数量、订单金额、订单奖励金、微信手续费、平台手续费 ok")

	err = q.UpdateActivityUserOrderStatSinceOrderPayed(ctx, sqlc.UpdateActivityUserOrderStatSinceOrderPayedParams{
		ActivityID:  activityID,
		OrderCount:  int32(aggRetOfOrderForward.OrderCount),
		OrderAmount: aggRetOfOrderForward.OrderAmount,
		OrderBonus:  aggRetOfOrderForward.OrderBonus,
	})
	if err != nil {
		return
	}

	slog.Infof("3、新订单支付成功更新活动用户订单统计的正向下单部分字段 ok")
	return
}

// UpdateActivityOrderStatSinceOrderRefundedParam 售后订单完成更新活动订单统计参数
type UpdateActivityOrderStatSinceOrderRefundedParam struct {
	OrderPtr     *sqlc.Order
	AfterSalePtr *sqlc.AfterSale
}

// UpdateActivityOrderStatSinceAfterSaleFinished 售后订单完成更新活动订单统计
func (s *ActivityServiceImp) UpdateActivityOrderStatSinceAfterSaleFinished(ctx context.Context, q *sqlc.Queries, p UpdateActivityOrderStatSinceOrderRefundedParam) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	activityID := p.AfterSalePtr.ActivityID
	activityOrderStatLocked, err := s.EnsureActivityOrderStat(ctx, q, true, activityID)
	if err != nil {
		return
	}
	slog.Infof("1、售后-确保获取锁定的活动订单统计记录(%d) ok", activityID)

	newRefundBuyerCount, err := q.AggrBuyerCountOfAfterSaleByActivityID(ctx, activityID)
	if err != nil {
		return
	}
	slog.Infof("2、统计当前售后单退款成功后该活动的售后单用户数量 ok")
	newRefundOrderCount, err := q.AggrOrderCountOfAfterSaleByActivityID(ctx, activityID)
	if err != nil {
		return
	}
	slog.Infof("3、统计当前售后单退款成功后该活动的存在售后的订单数量 ok")

	aggRetOfOrderBackward, err := q.AggrOrderBackwardByActivityID(ctx, activityID)
	if err != nil {
		return
	}
	slog.Infof("4、统计当前售后单退款成功后订单活动的售后单数量、订单退款金额、回退订单奖励金、回退微信手续费、回退平台手续费 ok")
	// 整单退可以退运费

	err = q.UpdateActivityOrderStatSinceAfterSaleFinished(ctx, sqlc.UpdateActivityOrderStatSinceAfterSaleFinishedParams{
		ActivityID:               activityID,
		RefundBuyerCount:         int32(newRefundBuyerCount),
		RefundOrderCount:         int32(newRefundOrderCount),
		RefundOrderAmount:        aggRetOfOrderBackward.RefundOrderAmount,
		RefundOrderBonus:         aggRetOfOrderBackward.RefundOrderBonus,
		RefundFee:                activityOrderStatLocked.RefundFee,
		RefundWxpayCommission:    aggRetOfOrderBackward.RefundWxpayCommission,
		RefundPlatformCommission: aggRetOfOrderBackward.RefundPlatformCommission,
	})
	if err != nil {
		return
	}

	slog.Infof("5、售后订单完成更新活动订单统计反向退款部分字段 ok")
	return
}

// UpdateActivityUserOrderStatSinceAfterSaleFinishedParam 售后订单退款更新活动用户订单统计参数
type UpdateActivityUserOrderStatSinceAfterSaleFinishedParam struct {
	OrderPtr     *sqlc.Order
	AfterSalePtr *sqlc.AfterSale
}

// UpdateActivityOrderStatSinceAfterSaleFinished 售后订单退款更新活动用户订单统计
func (s *ActivityServiceImp) UpdateActivityUserOrderStatSinceAfterSaleFinished(ctx context.Context, q *sqlc.Queries, p UpdateActivityUserOrderStatSinceAfterSaleFinishedParam) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	activityID := p.AfterSalePtr.ActivityID
	userID := p.AfterSalePtr.UserID
	activityUserOrderStatLocked, err := s.EnsureActivityUserOrderStat(ctx, q, true, activityID, userID)
	if err != nil {
		return
	}
	slog.Infof("1、售后-确保获取锁定的活动用户订单统计记录(%d)(%d)(%d) ok", activityID, userID, activityUserOrderStatLocked.ID)

	newRefundOrderCount, err := q.AggrOrderCountOfAfterSaleByActivityIDAndUserID(ctx, sqlc.AggrOrderCountOfAfterSaleByActivityIDAndUserIDParams{
		ActivityID: activityID,
		UserID:     userID,
	})
	if err != nil {
		return
	}
	slog.Infof("2、统计当前售后单退款成功后该活动的存在售后的用户订单数量 ok")

	aggRetOfOrderBackward, err := q.AggrOrderBackwardByActivityIDAndUserID(ctx, sqlc.AggrOrderBackwardByActivityIDAndUserIDParams{
		ActivityID: activityID,
		UserID:     userID,
	})
	if err != nil {
		return
	}
	slog.Infof("3、统计当前订单支付成功后用该用户订单活动的订单数量、订单金额、订单奖励金、微信手续费、平台手续费 ok")

	err = q.UpdateActivityUserOrderStatSinceAfterSaleFinished(ctx, sqlc.UpdateActivityUserOrderStatSinceAfterSaleFinishedParams{
		ActivityID:        activityID,
		RefundOrderCount:  int32(newRefundOrderCount),
		RefundOrderAmount: aggRetOfOrderBackward.RefundOrderAmount,
		RefundOrderBonus:  aggRetOfOrderBackward.RefundBonusAmount,
	})
	if err != nil {
		return
	}

	slog.Infof("24售后订单完成更新活动用户订单统计反向退款部分字段 ok")
	return
}

// AggrActivityExposureStatsByParentActivityID 统计品牌活动id下的所有代言活动曝光信息
func (s *ActivityServiceImp) AggrActivityExposureStatsByParentActivityID(ctx context.Context, q *sqlc.Queries, activityID int64) (aggrExposure sqlc.AggrActivityExposureStatsByParentActivityIDRow, err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	aggrExposure, sqlErr := q.AggrActivityExposureStatsByParentActivityID(ctx, sqlc.NInt64FromInt64(activityID))
	if sqlErr != nil {
		if sql.ErrNoRows != sqlErr {
			err = sqlErr
			return
		}
		slog.Infof("找不到品牌活动id下的所有代言活动曝光信息, 使用默认")
	}
	return
}

// AggrActivityOrderStatsByParentActivityID 统计品牌活动id下的所有代言活动订单信息
func (s *ActivityServiceImp) AggrActivityOrderStatsByParentActivityID(ctx context.Context, q *sqlc.Queries, activityID int64) (aggrOrder sqlc.AggrActivityOrderStatsByParentActivityIDRow, err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	aggrOrder, sqlErr := q.AggrActivityOrderStatsByParentActivityID(ctx, sqlc.NInt64FromInt64(activityID))
	if sqlErr != nil {
		if sql.ErrNoRows != sqlErr {
			err = sqlErr
			return
		}
		slog.Infof("找不到品牌活动id下的所有代言活动订单信息, 使用默认")
	}
	return
}

// AggrActivityUserOrderStatsForOrderAmoumntByParentActivityID 统计品牌活动id下的所有代言活动订单金额
func (s *ActivityServiceImp) AggrActivityUserOrderStatsForOrderAmoumntByParentActivityID(ctx context.Context, q *sqlc.Queries, activityID int64) (aggrOrderAmount int64, err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	aggrOrderAmount, sqlErr := q.AggrActivityUserOrderStatsForOrderAmoumntByParentActivityID(ctx, sqlc.NInt64FromInt64(activityID))
	if sqlErr != nil {
		if sql.ErrNoRows != sqlErr {
			err = sqlErr
			return
		}
		slog.Infof("找不到品牌活动id下的所有代言活动订单金额, 使用默认")
	}
	return
}

// AggrActivityUserOrderStatsForSpokesmanByParentActivityID 统计品牌活动id下按代言人代言活动分组的帮卖信息汇总
func (s *ActivityServiceImp) AggrActivityUserOrderStatsForSpokesmanByParentActivityID(ctx context.Context, q *sqlc.Queries, activityID int64) (aggrRet []sqlc.AggrActivityUserOrderStatsForSpokesmanByParentActivityIDRow, err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	aggrRet, sqlErr := q.AggrActivityUserOrderStatsForSpokesmanByParentActivityID(ctx, sqlc.NInt64FromInt64(activityID))
	if sqlErr != nil {
		if sql.ErrNoRows != sqlErr {
			err = sqlErr
			return
		}
		slog.Infof("找不到品牌活动id下按代言人代言活动分组的帮卖信息汇总, 使用默认")
	}
	return
}

// RankActivityUserOrderStatsOverOrderAmountForSpokesmanByParentActivityID 排名品牌活动id下按代言人代言活动销售额后列出帮卖信息汇总
func (s *ActivityServiceImp) RankActivityUserOrderStatsOverOrderAmountForSpokesmanByParentActivityID(ctx context.Context, q *sqlc.Queries, topRankNumber uint32, activityID int64) (aggrRet []sqlc.RankActivityUserOrderStatsOverOrderAmountForSpokesmanByParentActivityIDRow, err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	aggrRet, sqlErr := q.RankActivityUserOrderStatsOverOrderAmountForSpokesmanByParentActivityID(ctx, sqlc.RankActivityUserOrderStatsOverOrderAmountForSpokesmanByParentActivityIDParams{
		ParentActivityID: sqlc.NInt64FromInt64(activityID),
		TopRankNumber:    int32(topRankNumber),
	})
	if sqlErr != nil {
		if sql.ErrNoRows != sqlErr {
			err = sqlErr
			return
		}
		slog.Infof("找不到品牌活动id下按代言人代言活动分组的帮卖信息汇总, 使用默认")
	}
	return
}
